home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / text / tex / tgrind.lha / TGrind / vgrindefs.c < prev   
C/C++ Source or Header  |  1993-01-04  |  6KB  |  286 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)vgrindefs.c    4.3 (Berkeley) 12/11/84";
  3. #endif
  4.  
  5. /* Copyright (c) 1979 Regents of the University of California */
  6.  
  7. #define    BUFSIZ    1024
  8. #define MAXHOP    32    /* max number of tc= indirections */
  9.  
  10. #include <ctype.h>
  11. /*
  12.  * grindcap - routines for dealing with the language definitions data base
  13.  *    (code stolen almost totally from termcap)
  14.  *
  15.  * BUG:        Should use a "last" pointer in tbuf, so that searching
  16.  *        for capabilities alphabetically would not be a n**2/2
  17.  *        process when large numbers of capabilities are given.
  18.  * Note:    If we add a last pointer now we will screw up the
  19.  *        tc capability. We really should compile termcap.
  20.  *
  21.  * Essentially all the work here is scanning and decoding escapes
  22.  * in string capabilities.  We don't use stdio because the editor
  23.  * doesn't, and because living w/o it is not hard.
  24.  */
  25.  
  26. static    char *tbuf;
  27. static    char *filename;
  28. static    int hopcount;    /* detect infinite loops in termcap, init 0 */
  29. static char *tdecode(char *, char **);
  30. #include "vgrindefs_protos.h"
  31. #include <fcntl.h>
  32. #include <string.h>
  33.  
  34. /*
  35.  * Get an entry for terminal name in buffer bp,
  36.  * from the termcap file.  Parse is very rudimentary;
  37.  * we just notice escaped newlines.
  38.  */
  39. int tgetent(char *bp, char *name, char *file)
  40. {
  41.     register char *cp;
  42.     register int c;
  43.     register int i = 0, cnt = 0;
  44.     char ibuf[BUFSIZ];
  45.     int tf;
  46.  
  47.     tbuf = bp;
  48.     tf = 0;
  49.     filename = file;
  50.     tf = open(filename, 0);
  51.     if (tf < 0)
  52.         return (-1);
  53.     for (;;) {
  54.         cp = bp;
  55.         for (;;) {
  56.             if (i == cnt) {
  57.                 cnt = read(tf, ibuf, BUFSIZ);
  58.                 if (cnt <= 0) {
  59.                     close(tf);
  60.                     return (0);
  61.                 }
  62.                 i = 0;
  63.             }
  64.             c = ibuf[i++];
  65.             if (c == '\n') {
  66.                 if (cp > bp && cp[-1] == '\\'){
  67.                     cp--;
  68.                     continue;
  69.                 }
  70.                 break;
  71.             }
  72.             if (cp >= bp+BUFSIZ) {
  73.                 write(2,"Vgrind entry too long\n", 23);
  74.                 break;
  75.             } else
  76.                 *cp++ = c;
  77.         }
  78.         *cp = 0;
  79.  
  80.         /*
  81.          * The real work for the match.
  82.          */
  83.         if (tnamatch(name)) {
  84.             close(tf);
  85.             return(tnchktc());
  86.         }
  87.     }
  88. }
  89.  
  90. /*
  91.  * tnchktc: check the last entry, see if it's tc=xxx. If so,
  92.  * recursively find xxx and append that entry (minus the names)
  93.  * to take the place of the tc=xxx entry. This allows termcap
  94.  * entries to say "like an HP2621 but doesn't turn on the labels".
  95.  * Note that this works because of the left to right scan.
  96.  */
  97. int tnchktc(void)
  98. {
  99.     register char *p, *q;
  100.     char tcname[16];    /* name of similar terminal */
  101.     char tcbuf[BUFSIZ];
  102.     char *holdtbuf = tbuf;
  103.     int l;
  104.  
  105.     p = tbuf + strlen(tbuf) - 2;    /* before the last colon */
  106.     while (*--p != ':')
  107.         if (p<tbuf) {
  108.             write(2, "Bad vgrind entry\n", 18);
  109.             return (0);
  110.         }
  111.     p++;
  112.     /* p now points to beginning of last field */
  113.     if (p[0] != 't' || p[1] != 'c')
  114.         return(1);
  115.     strcpy(tcname,p+3);
  116.     q = tcname;
  117.     while (q && *q != ':')
  118.         q++;
  119.     *q = 0;
  120.     if (++hopcount > MAXHOP) {
  121.         write(2, "Infinite tc= loop\n", 18);
  122.         return (0);
  123.     }
  124.     if (tgetent(tcbuf, tcname, filename) != 1)
  125.         return(0);
  126.     for (q=tcbuf; *q != ':'; q++)
  127.         ;
  128.     l = p - holdtbuf + strlen(q);
  129.     if (l > BUFSIZ) {
  130.         write(2, "Vgrind entry too long\n", 23);
  131.         q[BUFSIZ - (p-tbuf)] = 0;
  132.     }
  133.     strcpy(p, q+1);
  134.     tbuf = holdtbuf;
  135.     return(1);
  136. }
  137.  
  138. /*
  139.  * Tnamatch deals with name matching.  The first field of the termcap
  140.  * entry is a sequence of names separated by |'s, so we compare
  141.  * against each such name.  The normal : terminator after the last
  142.  * name (before the first field) stops us.
  143.  */
  144. int tnamatch(char *np)
  145. {
  146.     register char *Np, *Bp;
  147.  
  148.     Bp = tbuf;
  149.     if (*Bp == '#')
  150.         return(0);
  151.     for (;;) {
  152.         for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
  153.             continue;
  154.         if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
  155.             return (1);
  156.         while (*Bp && *Bp != ':' && *Bp != '|')
  157.             Bp++;
  158.         if (*Bp == 0 || *Bp == ':')
  159.             return (0);
  160.         Bp++;
  161.     }
  162. }
  163.  
  164. /*
  165.  * Skip to the next field.  Notice that this is very dumb, not
  166.  * knowing about \: escapes or any such.  If necessary, :'s can be put
  167.  * into the termcap file in octal.
  168.  */
  169. static char *tskip(char *bp)
  170. {
  171.  
  172.     while (*bp && *bp != ':')
  173.         bp++;
  174.     if (*bp == ':')
  175.         bp++;
  176.     return (bp);
  177. }
  178.  
  179. #if 0
  180. /* This is not needed! */
  181. /*
  182.  * Return the (numeric) option id.
  183.  * Numeric options look like
  184.  *    li#80
  185.  * i.e. the option string is separated from the numeric value by
  186.  * a # character.  If the option is not found we return -1.
  187.  * Note that we handle octal numbers beginning with 0.
  188.  */
  189. int tgetnum(char *id)
  190. {
  191.     register int i, base;
  192.     register char *bp = tbuf;
  193.  
  194.     for (;;) {
  195.         bp = tskip(bp);
  196.         if (*bp == 0)
  197.             return (-1);
  198.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  199.             continue;
  200.         if (*bp == '@')
  201.             return(-1);
  202.         if (*bp != '#')
  203.             continue;
  204.         bp++;
  205.         base = 10;
  206.         if (*bp == '0')
  207.             base = 8;
  208.         i = 0;
  209.         while (isdigit(*bp))
  210.             i *= base, i += *bp++ - '0';
  211.         return (i);
  212.     }
  213. }
  214. #endif
  215.  
  216. /*
  217.  * Handle a flag option.
  218.  * Flag options are given "naked", i.e. followed by a : or the end
  219.  * of the buffer.  Return 1 if we find the option, or 0 if it is
  220.  * not given.
  221.  */
  222. int tgetflag(char *id)
  223. {
  224.     register char *bp = tbuf;
  225.  
  226.     for (;;) {
  227.         bp = tskip(bp);
  228.         if (!*bp)
  229.             return (0);
  230.         if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
  231.             if (!*bp || *bp == ':')
  232.                 return (1);
  233.             else if (*bp == '@')
  234.                 return(0);
  235.         }
  236.     }
  237. }
  238.  
  239. /*
  240.  * Get a string valued option.
  241.  * These are given as
  242.  *    cl=^Z
  243.  * Much decoding is done on the strings, and the strings are
  244.  * placed in area, which is a ref parameter which is updated.
  245.  * No checking on area overflow.
  246.  */
  247. char *tgetstr(char *id, char **area)
  248. {
  249.     register char *bp = tbuf;
  250.  
  251.     for (;;) {
  252.         bp = tskip(bp);
  253.         if (!*bp)
  254.             return (0);
  255.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  256.             continue;
  257.         if (*bp == '@')
  258.             return(0);
  259.         if (*bp != '=')
  260.             continue;
  261.         bp++;
  262.         return (tdecode(bp, area));
  263.     }
  264. }
  265.  
  266. /*
  267.  * Tdecode does the grung work to decode the
  268.  * string capability escapes.
  269.  */
  270. static char *tdecode(char *str, char **area)
  271. {
  272.     register char *cp;
  273.     register int c;
  274.  
  275.     cp = *area;
  276.     while (c = *str++) {
  277.         if (c == ':' && *(cp-1) != '\\')
  278.         break;
  279.         *cp++ = c;
  280.     }
  281.     *cp++ = 0;
  282.     str = *area;
  283.     *area = cp;
  284.     return (str);
  285. }
  286.